/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sg.edu.nus.iss.pacman.ui;

import sg.edu.nus.iss.pacman.game.NodeType;
import sg.edu.nus.iss.pacman.game.Player;
import java.io.IOException;
import java.util.Vector;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

/**
 * A class to draw a maze.
 * @author fredy
 */
public class MazeBuilder
{
    private static int DOT_HEIGHT = 3;
    private static int DOT_WIDTH = 3;
    private static int NUM_X_BLOCK = 17;
    private static int NUM_Y_BLOCK = 23;
    private int startX;
    private int startY = 20;
    private int blockHeight = 0;
    private int blockWidth = 0;
    private Graphics graphics;
    private Image pacManRightImage;
    private Image pacManLeftImage;
    private Image pacManUpImage;
    private Image pacManDownImage;
    private Image ghostImageLeft;
    private Player pacMan;
    private Vector ghosts = new Vector();

    /**
     * Creates a new instance of MazeBuilder.
     * @param width the width
     * @param height the height
     * @param pacMan the Pacman
     * @param ghosts the list of ghosts
     */
    public MazeBuilder(int width, int height, Player pacMan, Vector ghosts)
    {
        blockWidth = Math.abs(width / NUM_X_BLOCK);
        startX = (width - (blockWidth * NUM_X_BLOCK)) / 2;
        blockHeight = Math.abs(height / NUM_Y_BLOCK);
        this.pacMan = pacMan;
        this.ghosts = ghosts;
        try
        {
            pacManRightImage = resizeImage(Image.createImage("/res/PacMan3right.gif"),
                blockWidth, blockHeight);
            pacManLeftImage = resizeImage(Image.createImage("/res/PacMan3left.gif"),
                blockWidth, blockHeight);
            pacManUpImage = resizeImage(Image.createImage("/res/PacMan3up.gif"),
                blockWidth, blockHeight);
            pacManDownImage = resizeImage(Image.createImage("/res/PacMan3down.gif"),
                blockWidth, blockHeight);
            ghostImageLeft = resizeImage(Image.createImage("/res/Ghost2.gif"),
                blockWidth, blockHeight);
        }
        catch (IOException ex)
        {
            throw new RuntimeException(ex.getMessage());
        }
    }

    /**
     * Draws the maze
     * @param maze the maze
     */
    public void draw(int[][] maze)
    {
        int y = startY;
        for (int i = 0; i < maze.length; i++)
        {
            int x = startX;
            for (int j = 0; j < maze[i].length; j++)
            {
                if (maze[i][j] == NodeType.WALL)
                {
                    getGraphics().setColor(ColorConstants.BLUE);
                    getGraphics().fillRect(x, y, blockWidth, blockHeight);
                }
                else if (maze[i][j] == NodeType.DOT)
                {
                    getGraphics().setColor(ColorConstants.BLACK);
                    getGraphics().fillRect(x, y, blockWidth, blockHeight);
                    getGraphics().setColor(ColorConstants.YELLOW);
                    getGraphics().fillRect(x + (blockWidth / 2), y + (blockHeight / 2),
                        DOT_WIDTH, DOT_HEIGHT);
                }
                else if (maze[i][j] == NodeType.PACMAN)
                {
                    getGraphics().setColor(ColorConstants.BLACK);
                    getGraphics().fillRect(x, y, blockWidth, blockHeight);
                    getGraphics().setColor(ColorConstants.YELLOW);
                    animate(getGraphics(), pacMan, x, y);
                }
                else if (maze[i][j] == NodeType.GHOST)
                {
                    getGraphics().setColor(ColorConstants.BLACK);
                    getGraphics().fillRect(x, y, blockWidth, blockHeight);
                    getGraphics().setColor(ColorConstants.YELLOW);
                    for (int k = 0; k < ghosts.size(); k++)
                    {
                        Player ghost = (Player) ghosts.elementAt(k);
                        animate(getGraphics(), ghost, x, y);
                    }
                }
                else if (maze[i][j] == NodeType.BLANK)
                {
                    getGraphics().setColor(ColorConstants.BLACK);
                    getGraphics().fillRect(x, y, blockWidth, blockHeight);
                }
                x += blockWidth;
            }
            y += blockHeight;
        }
    }

    private void animate(Graphics graphics, Player player, int x, int y)
    {
        Image image = getImage(player);
        if (player.getPosition() == Player.RIGHT)
        {
            graphics.drawImage(image, x, y, 0);
        }
        else if (player.getPosition() == Player.LEFT)
        {
            graphics.drawImage(image, x, y, 0);
        }
        else if (player.getPosition() == Player.DOWN)
        {
            graphics.drawImage(image, x, y, 0);
        }
        else if (player.getPosition() == Player.UP)
        {
            graphics.drawImage(image, x, y, 0);
        }
    }

    private Image getImage(Player player)
    {
        Image image = null;
        if (player.getPlayerType() == Player.PACMAN)
        {
            if (player.getPosition() == Player.LEFT)
            {
                image = pacManLeftImage;
            }
            else if (player.getPosition() == Player.RIGHT)
            {
                image = pacManRightImage;
            }
            else if (player.getPosition() == Player.UP)
            {
                image = pacManUpImage;
            }
            else if (player.getPosition() == Player.DOWN)
            {
                image = pacManDownImage;
            }
        }
        else if (player.getPlayerType() == Player.GHOST)
        {
            image = ghostImageLeft;
        }
        return image;
    }

    /**
     * Get the Graphics object.
     * @return the Graphics object
     */
    public Graphics getGraphics()
    {
        return graphics;
    }

    /**
     * Set the Graphics object.
     * @param graphics the Graphic object
     */
    public void setGraphics(Graphics graphics)
    {
        this.graphics = graphics;
    }
    /**
     * Resizes the image.
     * @param image the image that needs to be resized
     * @param newWidth the new width
     * @param newHeight the new height
     * @return the resized image
     */
    private Image resizeImage(Image image, int newWidth, int newHeight)
    {
        int sourceWidth = image.getWidth();
        int sourceHeight = image.getHeight();

        if (newHeight == -1)
        {
            newHeight = newWidth * sourceHeight / sourceWidth;
        }

        Image img = Image.createImage(newWidth, newHeight);
        Graphics g = img.getGraphics();

        for (int y = 0; y < newHeight; y++)
        {
            for (int x = 0; x < newWidth; x++)
            {
                g.setClip(x, y, 1, 1);
                int dx = x * sourceWidth / newWidth;
                int dy = y * sourceHeight / newHeight;
                g.drawImage(image, x - dx, y - dy, Graphics.LEFT | Graphics.TOP);
            }
        }

        Image immutableThumb = Image.createImage(img);

        return immutableThumb;
    }
}
